PROGRAM CCSD
!
! INCORE PROGRAM FOR CCSD CALCULATIONS 
!
use mod_iop
use mod_size
use mod_orbit
use mod_ioff 
implicit none
integer nvn, non, i0
integer ie, iend, ifij, ifab
integer ifia, it1, it2, iijkl, iijka 
integer it12, it22, ir12, ir22, iend2
integer iiabj, iabij, iabci, iabcd, ir1, ir2
integer ifmi, ifae, ifme
integer iwmnij, iwmbej
integer maxcore, nneed, icrsizg
integer, external :: irpdso, idsymsoc
real*8 tt1, tt2, rt1, rt2
real*8 escf, eccsd, eccsdt
real*4, allocatable :: icore(:) 
real*4,device, allocatable :: icoreg(:) 
!
call cpu_time(tt1); call walltimeso(rt1)
!call readcommon
!call readmodule
call read_mod
!if(ldebug) then 
  write(6,*)'totgpu', totgpu
  write(6,*)'nbasis', noa, nva
!icrsiz = 1024*1024*1024/8*100 ! 110GB
!icrsizg = 1024*1024*1024/8*10 ! 11GB
!endif
allocate(icore(icrsiz))
!
! various lengths
!
nvn = nva + nvb
non = noa + nob
!
ie=1
iend=ie+(nvn+non)*isd
!
!memory fo t1, t2 and r1, r2
it1 = iend
it2 = it1 + nifvo*isd
ir1 = it2 + nioi3*isd
ir2 = ir1 + nifvo*isd
iend = ir2 +nioi3*isd
!
! memory for fock matrices
!
ifij=iend
ifab=ifij +nifoo*isd
ifia=ifab +nifvv*isd
iend =ifia+nifvo*isd
!
! memory for fae, fmi and fme 
!
ifmi=iend
ifae=ifmi +nifoo*isd
ifme=ifae +nifvv*isd
iend =ifme+nifvo*isd
!
! memory for small two-electron integrals
!
if(ldebug) then 
  write(6,'(A, I14, I14, I14, I14)')'nioi', nioi1, nioi2, nioi3, nioi4
endif
iijkl = iend 
iwmnij = iijkl +nioi1*isd
iijka = iwmnij +nioi1*isd
iabij = iijka  +nioi2*isd
iiabj = iabij  +nioi3*isd
iwmbej = iiabj +nioi4*isd  ! iiabj(bbaa)  = iiabj(aabb)
iend = iwmbej  +nioi4*isd   ! wmbej(aabb) /= wmbej(bbaa)
nneed = iend + nvvoo*4*isd
write(6,*)'size of iijkl          ', nioi1/1024.d0/1024.d0*4*isd, 'MB'
write(6,*)'size of iijka          ', nioi2/1024.d0/1024.d0*4*isd, 'MB'
write(6,*)'size of t2 and r2      ', nioi3/1024.d0/1024.d0*4*isd, 'MB'
write(6,*)'size of wmbej and iiabj', nioi4/1024.d0/1024.d0*4*isd, 'MB'
write(6,*)'size of iabci          ', nioi5/1024.d0/1024.d0*4*isd, 'MB'
write(6,*)'size of iabcd          ', nioi6/1024.d0/1024.d0*4*isd, 'MB'
!
write(6,*)'memroy needed for small', nneed/1024.d0/1024.d0*4, 'MB'
if(nneed>icrsiz) then 
   write(6,*)'memory is not enough for small terms'
   stop
endif

if(nneed>igpusize) then  
   write(6,*)'memory is not enough for gpu' 
!   igpu=0; totgpu=0
endif
!
! memory for large two-electron integerals
!
iabci = iend
iend = iabci + nioi5*isd
nneed = iend + max(nvvoo*4*isd, nvvvo*2*isd)
ioiabci=0
write(6,*)'memroy needed for iabci', nneed/1024.d0/1024.d0*4, 'MB'
if(nneed>icrsiz) then  
   write(6,*)'memory is not enough for iabci terms'
   ioiabci=1
   iend = iend - nioi5*isd 
   write(6,*)'===attention!!! iabci terms was calculated with IO'
endif
if(nneed<igpusize) then  
   write(6,*)'iabci can be calculated in GPU  '
   igpuabci=1
   igpuleft = igpusize-iend
   write(6,*)'memory left in GPU', igpuleft/1024/1024*4, 'MB'
endif
! 
iabcd = iend 
iend  = iabcd + nioi6*isd
nneed = iend + max(nvvoo*4*isd,nvvvo*2*isd)
write(6,*)'memroy needed for iabcd', nneed/1024.d0/1024.d0*4.d0, 'MB'
if(nneed>icrsiz) then 
   ioiabcd=1
   iend = iend - nioi6*isd 
   write(6,*)'===attention!!! iabcd terms was calculated with IO'
endif
!
if(nneed<igpusize) then
   write(6,*)'iabcd can be calculated in GPU  '
   igpuabcd=1
endif
!
!ioiabcd=1
!ioiabci=1
maxcore = icrsiz - iend 
nneed = iend + max(nvvoo*4*isd, nvvvo*2*isd)
write(6,*)'memroy needed in ccsd calculation', nneed/1024.d0/1024.d0*4, 'MB'
write(6,*)'memory left   in this calculation', maxcore/1024.d0/1024.d0*4, 'MB' 
 call run(icore(ie),                                           &   
          icore(it1), icore(it2), icore(ir1), icore(ir2),      &
          icore(ifij),icore(ifab),icore(ifia),                 &
          icore(ifae), icore(ifmi), icore(ifme),               &
          icore(iijkl), icore(iwmnij), icore(iijka),           &
          icore(iabij), icore(iiabj), icore(iwmbej),           &
          icore(iabci), icore(iabcd), icore(iend),             &
          maxcore, escf, eccsd, eccsdt)                    
call put_t(icore(it1), icore(it2), icore(iend))
call cpu_time(tt2); call walltimeso(rt2)
write(6,*)'cpu and real time for ccsd', tt2-tt1, rt2-rt1
!
end



















